package com.senseuni.da.utils;

import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbManager;
import android.media.AudioManager;
import android.os.Build;
import android.os.Environment;
import android.os.PowerManager;
import android.os.StatFs;
import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.view.WindowManager;

import com.elvishew.xlog.XLog;
import com.senseuni.da.BuildConfig;
import com.senseuni.da.MyApplication;
import com.senseuni.da.R;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AppUtils {

    public static void getDeviceInfo(Context context) {
        //磁盘信息
        // 获取StorageManager实例
        StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getPath());
        //存储块总数量
        long blockCount = statFs.getBlockCountLong();
        //块大小
        long blockSize = statFs.getBlockSizeLong();
        //可用块数量
        long availableCount = statFs.getAvailableBlocksLong();
        //剩余块数量，注：这个包含保留块（including reserved blocks）即应用无法使用的空间
        long freeBlocks = statFs.getFreeBlocksLong();
        //这两个方法是直接输出总内存和可用空间，也有getFreeBytes
        //API level 18（JELLY_BEAN_MR2）引入
        long totalSize = statFs.getTotalBytes();
        long availableSize = statFs.getAvailableBytes();

        XLog.d("total = " + getUnit(totalSize));
        XLog.d("availableSize = " + getUnit(availableSize));

        //这里可以看出 available 是小于 free ,free 包括保留块。
        XLog.d("total = " + getUnit(blockSize * blockCount));
        XLog.d("available = " + getUnit(blockSize * availableCount));
        XLog.d("free = " + getUnit(blockSize * freeBlocks));

        //版本信息
        String version = BuildConfig.VERSION_NAME;
        //媒体音量
        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        int streamVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        XLog.d( "GetDeviceInfo: streamVolume:" + streamVolume);
        //屏幕状态
        XLog.d("IsKeyguardLocked:%s,IsScreenOn:%s", IsKeyguardLocked(context), IsScreenOn(context));
        PrintScreenInfo(context);
    }

    public static boolean IsKeyguardLocked(Context context){
        KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
        return keyguardManager.isKeyguardLocked();
    }

    public static boolean IsScreenOn(Context context) {
        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        return powerManager.isInteractive();
    }

    public static void PrintScreenInfo(Context context) {
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metrics = new DisplayMetrics();
        if (windowManager != null) {
            windowManager.getDefaultDisplay().getMetrics(metrics);
            XLog.d("PrintScreenInfo: Width:" + metrics.widthPixels + ",height:" + metrics.heightPixels + ",density:" + metrics.density);
        } else {
            XLog.d( "PrintScreenInfo get fail" );
        }
    }

    private static final String[] units = {
            "B", "KB", "MB", "GB", "TB"};

    /**
     * 单位转换
     */
    private static String getUnit(float size) {

        int index = 0;
        while (size > 1024 && index < 4) {

            size = size / 1024;
            index++;
        }
        return String.format(Locale.getDefault(), " %.2f %s", size, units[index]);
    }

    /**
     * Base64加密字符串
     * @param content -- 待加密字符串
     */
    public static String base64Encode(String content) {
        byte[] bytesEncoded = Base64.encode(content.getBytes(), Base64.NO_WRAP);
        return new String(bytesEncoded);
    }

    private static final String PASSWORD = "mvtlabs";
    public static String generateKey(String stochastic, String deviceId) {
        String str = stochastic + deviceId + PASSWORD;
        return md5(str);
    }

    public static String md5(String string) {
        if (TextUtils.isEmpty(string)) {
            return "";
        }
        MessageDigest md5;
        try {
            md5 = MessageDigest.getInstance("MD5");
            byte[] bytes = md5.digest(string.getBytes());
            String result = "";
            for (byte b : bytes) {
                String temp = Integer.toHexString(b & 0xff);
                if (temp.length() == 1) {
                    temp = "0" + temp;
                }
                result += temp;
            }
            return result;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String getDeviceId() {
        Context context = MyApplication.app.getApplicationContext();
        String serial = Build.SERIAL;
//        String imei = getImei(context);
//        if (TextUtils.isEmpty(imei)) {
//            //某些设备是拿不到imei的，比如一体机设备，通过获取ANDROID_ID作为唯一ID
//            imei = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
//        }
        if (TextUtils.isEmpty(serial) || "unknown".equalsIgnoreCase(serial)) {
            return getUniqueId(context);
        }
        return serial;
    }


    //10.0及以上系统生成设备号
    protected static String getUniqueId(Context context) {
        @SuppressLint("HardwareIds")
        // ANDROID_ID是设备第一次启动时产生和存储的64bit的一个数，当设备被wipe后该数重置。
        String androidID = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
        @SuppressLint("HardwareIds")
        String id = androidID + Build.SERIAL; // +硬件序列号
        return AppUtils.md5(id).toUpperCase();
    }

    public static String getImei(Context context) {
        try {
            TelephonyManager telephonyManager = (TelephonyManager) context
                    .getSystemService(Context.TELEPHONY_SERVICE);
            String imei = telephonyManager.getImei();
            if (!TextUtils.isEmpty(imei)) {
                return imei;
            }
        } catch (Exception e) {
            XLog.e("get imei fail:%s", e.getMessage());
            e.printStackTrace();
        }
        return "";
    }

    public static String getUrl(Context context, String key) {
        try {
            String packageName = getPackageName(context);
            Class buildConfig = Class.forName(packageName + ".BuildConfig");
            Field filed = buildConfig.getField(key);
            String result = filed.get(null).toString();
            if (result.startsWith("MVT_")) {
                String[] array = result.split("@");
                if (array.length == 0) {
                    return result;
                }
                filed = buildConfig.getField(array[0]);
                result = filed.get(null).toString();
                if (array.length > 1) {
                    return result + array[1];
                }
                return result;
            } else {
                return result;
            }
        } catch (Throwable t) {
            // Do nothing
            return "";
        }
    }

    public static String getPackageName(Context context) {
        return context.getApplicationInfo().packageName;
    }

    public static String getBaseUrl(Context context) {
        return TextUtils.isEmpty(getUrl(context, "MVT_BASE")) ? "http://baidu.com" : getUrl(context, "MVT_BASE");
    }

    public static boolean install(String apkPath) {
        boolean result = false;
        DataOutputStream dataOutputStream = null;
        BufferedReader errorStream = null;
        try {
            // 申请su权限
            Process process = Runtime.getRuntime().exec("su");
            dataOutputStream = new DataOutputStream(process.getOutputStream());
            // 执行pm install命令
            String command = "pm install -r " + apkPath + "\n";
            dataOutputStream.write(command.getBytes(Charset.forName("utf-8")));
            dataOutputStream.flush();
            dataOutputStream.writeBytes("exit\n");
            dataOutputStream.flush();
            process.waitFor();
            errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String msg = "";
            String line;
            // 读取命令的执行结果
            while ((line = errorStream.readLine()) != null) {
                msg += line;
            }
            XLog.d("TAG", "install msg is " + msg);
            // 如果执行结果中包含Failure字样就认为是安装失败，否则就认为安装成功
            if (!msg.contains("Failure")) {
                result = true;
            }
        } catch (Exception e) {
            XLog.e("TAG", e.getMessage(), e);
        } finally {
            try {
                if (dataOutputStream != null) {
                    dataOutputStream.close();
                }
                if (errorStream != null) {
                    errorStream.close();
                }
            } catch (IOException e) {
                XLog.e("TAG", e.getMessage(), e);
            }
        }
        return result;
    }

    public static void screenOn() {
        XLog.d("screenOn");
        Context context = MyApplication.app.getApplicationContext();

        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        if (powerManager!= null) {
            if (!powerManager.isInteractive()) {
                ShellUtil.INSTANCE.execSU("input keyevent 26");

                AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
                if (audioManager != null) {
                    audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
                }
            }
        }
    }

    public static void screenOff() {
        //失败
        XLog.d("screenOff");
        Context context = MyApplication.app.getApplicationContext();
        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        if (powerManager!= null) {
            if (powerManager.isInteractive()) {
                ShellUtil.INSTANCE.execSU("input keyevent 26");

                AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
                if (audioManager != null) {
                    audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
                }
            }
        }
    }

    //定时唤醒屏幕
    public static void scheduleScreenOn(int interval) {
        Context context = MyApplication.app.getApplicationContext();
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(Intent.ACTION_SCREEN_ON);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
        long firstTime = SystemClock.elapsedRealtime() + interval * 60 * 1000;
        //AlarmManager.ELAPSED_REALTIME_WAKEUP 相对时间
        //AlarmManager.RTC_WAKEUP 绝对时间
        //AlarmManager.RTC 相对RTC时间
        //AlarmManager.RTC_WAKEUP 绝对RTC时间
        //AlarmManager.ELAPSED_REALTIME 相对elapsedRealtime()时间
        //AlarmManager.ELAPSED_REALTIME_WAKEUP 相对elapsedRealtime()时间并�����CPU
        //AlarmManager.INTERVAL_FIFTEEN_MINUTES 15分钟间隔
        //AlarmManager.INTERVAL_HOUR 1小时间隔
        //AlarmManager.INTERVAL_DAY 1天间隔
        //AlarmManager.INTERVAL_WEEKDAY 工作日间隔
        //AlarmManager.INTERVAL_WEEKEND 周末间隔
        //AlarmManager.INTERVAL_INDEFINITE 无限循环
        //AlarmManager.INTERVAL_CANCEL CANCELED 已取消的循环
        alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, interval * 60 * 1000, pendingIntent);
    }

    //定时休眠屏幕
    public static void scheduleScreenOff(int interval) {
        Context context = MyApplication.app.getApplicationContext();
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(Intent.ACTION_SCREEN_OFF);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
        long firstTime = SystemClock.elapsedRealtime() + interval * 60 * 1000;
        alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, interval * 60 * 1000, pendingIntent);
    }

    public static void setVolume(int volume) {
        XLog.d("setVolume=" + volume);
        Context context = MyApplication.app.getApplicationContext();
        int setVolume = (15 * volume) / 100;
        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        if (audioManager != null) {
            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, setVolume, 0);
        }
    }

    public static int systemVolumeTo(int volume) {
        //100/x = 15/y
        return  (100 * volume) / 15;
    }

    public static int toSystemVolume(int volume) {
        return  (15 * volume) / 100;
    }

    //OK
    public static void shutdown() {
        Intent intent = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN");
        intent.putExtra("android.intent.extra.KEY_CONFIRM", false);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        MyApplication.app.getApplicationContext().startActivity(intent);
    }

    //OK
    public static void reboot() {
        Intent intent = new Intent(Intent.ACTION_REBOOT);
        intent.putExtra("nowait", 1);
        intent.putExtra("interval", 1);
        intent.putExtra("window", 0);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        MyApplication.app.getApplicationContext().startActivity(intent);
    }

    //TODO 待验证
    public static void reboot2() {
        ShellUtil.INSTANCE.execSU("reboot");
    }

    public static void rebootApp() {
        Context context = MyApplication.app.getApplicationContext();
        Intent intent = context.getPackageManager().getLaunchIntentForPackage(BuildConfig.APPLICATION_ID);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        context.startActivity(intent);

        // 关闭当前进程
        int pid = android.os.Process.myPid();
        android.os.Process.killProcess(pid);
    }

    public static void disableTouch() {
        ShellUtil.INSTANCE.execSU("rm -rf /dev/input/event3");
    }

    public static String getFilename(String url) {
        //https://ray-dev.oss-cn-hangzhou.aliyuncs.com/pic1.jpg
        if (TextUtils.isEmpty(url)) {
            return "";
        }
        int index = url.lastIndexOf("/");
        if (index == -1) {
            return url;
        }
        return url.substring(index + 1);
    }

    public static void saveBootTimes() {
        int bootTimes = getBootTimes();
        bootTimes++;
        MmkvUtil.getInstance().put("boot_times", bootTimes);
    }

    public static int getBootTimes() {
        return MmkvUtil.getInstance().getInt("boot_times", 0);
    }

    public static void saveAppStartTime() {
        MmkvUtil.getInstance().put("app_start_time", System.currentTimeMillis());
    }

    public static long getAppStartTime() {
        return MmkvUtil.getInstance().getLong("app_start_time", 0L);
    }

    public static int getVolume() {
        return MmkvUtil.getInstance().getInt("volume", 35);
    }

    public static void saveVolume(int volume) {
        MmkvUtil.getInstance().put("volume", volume);
    }

    public static String getSignalDesc(Context context, int rssi) {
        if (rssi >= -30) {
            return context.getString(R.string.signal_very_good);
        }
        if (rssi >= -60) {
            return context.getString(R.string.signal_good);
        }
        if (rssi >= -80) {
            return context.getString(R.string.signal_bad);
        }
        return context.getString(R.string.signal_very_bad);
    }

    public static int getSignRes(Context context, int rssi) {
        if (rssi >= -30) {
            return R.drawable.ic_wifi_secret3;
        }
        if (rssi >= -60) {
            return R.drawable.ic_wifi_secret2;
        }
        if (rssi >= -80) {
            return R.drawable.ic_wifi_secret1;
        }
        return R.drawable.ic_wifi_secret1;
    }

    public static String convertImageToBase64(Context context, int resourceId) {
        InputStream inputStream = context.getResources().openRawResource(resourceId);
        byte[] byteArray = null;
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            byteArray = outputStream.toByteArray();
            outputStream.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Base64.encodeToString(byteArray, Base64.DEFAULT);
    }

    public static void saveBitmap(String base64, String savePath) {
        try {
            byte[] buffer = Base64.decode(base64, Base64.DEFAULT);
            FileOutputStream stream = new FileOutputStream(savePath);
            stream.write(buffer);
            stream.close();
        } catch (IOException e) {
            e.printStackTrace();
            XLog.e("save base64 picture error:" + e.getMessage());
        }
    }

    public static void enableMtp(Context context) {
        try {
            UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
            Class<?> usbManagerClass = usbManager.getClass();
            Method setFunctionMethod = usbManagerClass.getMethod("setFunction", String.class, boolean.class);
            setFunctionMethod.invoke(usbManager, "mtp", true); // 尝试设置为 MTP 模式
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void disableMtp(Context context) {
        try {
            UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
            Class<?> usbManagerClass = usbManager.getClass();
            Method setFunctionMethod = usbManagerClass.getMethod("setFunction", String.class, boolean.class);
            setFunctionMethod.invoke(usbManager, "", false); // 取消当前功能配置
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static boolean getAutoState(ContentResolver contentResolver, String name) {
        try {
            return Settings.Global.getInt(contentResolver, name) > 0;
        } catch (Settings.SettingNotFoundException ex) {
            XLog.e("cannot get auto state:" + name + " because:" + ex.getMessage());
            return false;
        }
    }

    public static String removeBase64Header(String base64) {
        if (base64 == null || base64.trim().isEmpty()) {
            return base64;
        }
        Matcher matcher = Pattern.compile("^data:[a-zA-Z0-9+/=._-]+;base64,").matcher(base64);
        if (matcher.find()) {
            return base64.substring(matcher.end());
        }
        return base64;
    }

    public static String convertImageToBase64(String path) {
        try {
            File imageFile = new File(path);
            if (!imageFile.exists()) {
                return null;
            }

            FileInputStream fileInputStream = new FileInputStream(imageFile);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

            byte[] buffer = new byte[4096];
            int length;

            while ((length = fileInputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, length);
            }

            fileInputStream.close();
            byteArrayOutputStream.close();

            byte[] imageBytes = byteArrayOutputStream.toByteArray();
            return Base64.encodeToString(imageBytes, Base64.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

}
